/*
*  Copyright 2019-2023 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.biz.service.impl;

//import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.BizException;
import me.zhengjie.modules.biz.domain.PrinceCityRegion;
import me.zhengjie.modules.biz.domain.req.PositionReq;
        import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import me.zhengjie.modules.biz.service.PrinceCityRegionService;
import me.zhengjie.modules.biz.domain.vo.PrinceCityRegionQueryCriteria;
import me.zhengjie.modules.biz.mapper.PrinceCityRegionMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import me.zhengjie.utils.PageUtil;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.io.IOException;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import me.zhengjie.utils.PageResult;
import org.springframework.web.client.RestTemplate;

import static me.zhengjie.modules.biz.constant.GaodeConstant.GAODE_KEY;
import static me.zhengjie.modules.biz.constant.GlobalConstant.NATIONWIDE;
import static me.zhengjie.modules.biz.domain.enums.ErrorCode.BODY_NOTNULL;

/**
* @description 服务实现
* @author yiwei.he
* @date 2024-04-07
**/
@Service
@RequiredArgsConstructor
@Slf4j
public class PrinceCityRegionServiceImpl extends ServiceImpl<PrinceCityRegionMapper, PrinceCityRegion> implements PrinceCityRegionService {

    private final PrinceCityRegionMapper princeCityRegionMapper;

    @Override
    public PageResult<PrinceCityRegion> queryAll(PrinceCityRegionQueryCriteria criteria, Page<Object> page){
        return PageUtil.toPage(princeCityRegionMapper.findAll(criteria, page));
    }

    @Override
    public List<PrinceCityRegion> queryAll(PrinceCityRegionQueryCriteria criteria){
        return princeCityRegionMapper.findAll(criteria);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(PrinceCityRegion resources) {
        save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(PrinceCityRegion resources) {
        PrinceCityRegion princeCityRegion = getById(resources.getId());
        princeCityRegion.copy(resources);
        saveOrUpdate(princeCityRegion);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<Integer> ids) {
        removeBatchByIds(ids);
    }

    @Override
    public void download(List<PrinceCityRegion> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (PrinceCityRegion princeCityRegion : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("城市id", princeCityRegion.getCityId());
            map.put("省市级别", princeCityRegion.getLevel());
            map.put("父级id", princeCityRegion.getParentId());
            map.put("parentArea",  princeCityRegion.getParentArea());
            map.put("区号", princeCityRegion.getAreaCode());
            map.put("名称", princeCityRegion.getName());
            map.put("合并名称", princeCityRegion.getMergerName());
            map.put("经度", princeCityRegion.getLng());
            map.put("纬度", princeCityRegion.getLat());
            map.put("是否展示", princeCityRegion.getIsShow());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    /**
     * 实现三级联动
     * @return
     */
    @Override
    public HashMap<String, Map<String, List<String>>> getArea() {
        // 省市区数据
        List<PrinceCityRegion> allProvinces = princeCityRegionMapper.findAll(new PrinceCityRegionQueryCriteria());
        // < 省,Map<市，区>>
        HashMap<String, Map<String, List<String>>> provinceCityRegionMap = new HashMap<>();
        List<PrinceCityRegion> provinces = allProvinces.stream().filter(r -> r.getLevel() == 0).collect(Collectors.toList());
        List<PrinceCityRegion> cities = allProvinces.stream().filter(r -> r.getLevel() == 1).collect(Collectors.toList());
        List<PrinceCityRegion> regions = allProvinces.stream().filter(r -> r.getLevel() == 2).collect(Collectors.toList());

        // 过滤掉香港、台湾和澳门,后续如果需要港澳台直接删除下面代码即可
        provinces = provinces.stream()
                .filter(p -> !p.getName().contains("香港") && !p.getName().contains("台湾") && !p.getName().contains("澳门"))
                .collect(Collectors.toList());

        // 填充省份数据
        for (PrinceCityRegion province : provinces) {
            // 市、区
            HashMap<String,List<String>> princeCityRegion = new HashMap<>();
            provinceCityRegionMap.put(province.getName(), princeCityRegion);
            // 获取省级别的id
            String provinceCode = province.getAreaCode();
            cities.forEach(c -> {
                // 将区域存放到市中
                if(Objects.equals(c.getParentArea().toString(), provinceCode)){
                    // 区域集合
                    ArrayList<String> regionList = new ArrayList<>();
                    // 城市id
                    String cityAreaCode = c.getAreaCode();
                    // 存放区级城市
                    regions.forEach(r->{
                        if(Objects.equals(r.getParentArea().toString(), cityAreaCode)){
                            regionList.add(r.getName());
                        }
                    });
                    // 存放市级城市
                    princeCityRegion.put(c.getName(),regionList);
                }
            });
        }
        return provinceCityRegionMap;
    }

    @Override
    public List<String> getPrince() {
        List<String> princeNameList;
        PrinceCityRegionQueryCriteria criteria = new PrinceCityRegionQueryCriteria();
        criteria.setLevel(0);
        List<PrinceCityRegion> princeList = princeCityRegionMapper.findAll(criteria);
        princeNameList = princeList.stream().map(PrinceCityRegion::getMergerName).collect(Collectors.toList());
        princeNameList.add(NATIONWIDE);
        Collections.reverse(princeNameList);
        return princeNameList;
    }

    @Override
    public String position(PositionReq req) {
        // https://restapi.amap.com/v3/geocode/regeo?output=xml&location=116.310003,39.991957&key=<用户的key>&radius=1000&extensions=all
        try {
            String apiUrl = "https://restapi.amap.com/v3/geocode/regeo?"
                    + "key=" + GAODE_KEY
                    + "&location=" + req.getLng() + "," + req.getLat()
                    + "&radius=1000&extensions=all";
            URL url = new URL(apiUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");
            BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));

            StringBuilder response = new StringBuilder();
            String output;
            while ((output = br.readLine()) != null) {
                response.append(output);
            }
            conn.disconnect();

            JsonObject jsonObject = JsonParser.parseString(response.toString()).getAsJsonObject();
            JsonObject addressComponent = jsonObject.getAsJsonObject("regeocode").getAsJsonObject("addressComponent");
            JsonElement cityElement = addressComponent.get("city");
            // 高德地图自治区有值时返回字符串，没有值时返回空数组，返回数据格式逻辑判断一下
            if (cityElement != null && cityElement.isJsonArray()) {
                JsonArray cityArray = cityElement.getAsJsonArray();
                if (!cityArray.isEmpty()) {
                    return cityArray.get(0).getAsString();
                }
            } else if (cityElement != null && cityElement.isJsonPrimitive()) {
                String city = cityElement.getAsString();
                if (city != null && !city.isEmpty()) {
                    return city;
                }
            }
            return addressComponent.get("province").getAsString();
        } catch (Exception e) {
            log.info("高德地图逆地理编码失败:" + e.getMessage());
            return "暂无";
        }
    }

    @Override
    public List<String> getCity(Integer code) throws BizException {
        PrinceCityRegionQueryCriteria criteria = new PrinceCityRegionQueryCriteria();
        if(code == null){
           throw new BizException(BODY_NOTNULL.getCode(),BODY_NOTNULL.getMessage());
        }
        criteria.setParentArea(code);
        return princeCityRegionMapper.findAll(criteria).stream()
                .sorted(Comparator.comparingInt(PrinceCityRegion::getId)).map(PrinceCityRegion::getName).collect(Collectors.toList());
    }

}